#!/usr/bin/python3
# -*- coding:utf-8 -*-
# @who:  spacelacc
# @date: 2025/04/24
# @func: Treeview for collecting data from parser dialog
# @vers: V1


from PySide6.QtCore    import Qt, QModelIndex
from PySide6.QtCore    import QAbstractItemModel
from PySide6.QtGui     import QPainter
from PySide6.QtWidgets import QTreeView

from PySide6.QtWidgets import QWidget, QApplication
import os


class CustomCounterTreeItem():
    def __init__(self, data):
        self.itparent = None
        self.children = []
        self.data = data

    def getChildren(self):
        return self.children

    def getItemParent(self):
        return self.itparent

    def getItemChild(self, which):
        if which < 0 or which >= len(self.children):
            return None
        return self.children[which]

    def getItemPos(self):
        try:
            return self.itparent.children.index(self)
        except:
            return -1

    # number of children
    def getRowCount(self):
        return len(self.children)

    # number of data contains in child
    def getColumnCount(self):
        return len(self.data)

    def getItemData(self, row):
        if row < 0 or row >= len(self.data):
            return None
        return self.data[row]

    def setItemData(self, row, value):
        if row < 0 or row >= len(self.data):
            return False
        self.data[row] = value
        return True

    def clearChildren(self):
        self.children.clear()

    def appendChild(self, child):
        child.itparent = self
        self.children.append(child)


class CustomCounterTreeModel(QAbstractItemModel):
    def __init__(self):
        super().__init__()
        self.root = CustomCounterTreeItem([''])

    def rowCount(self, index=QModelIndex()):
        if not index.isValid():
            inode = self.root
        else:
            inode = index.internalPointer()
        return inode.getRowCount()

    def columnCount(self, index=QModelIndex()):
        if not index.isValid():
            inode = self.root
        else:
            inode = index.internalPointer()
        return inode.getColumnCount()

    def parent(self, index):
        if not index.isValid():
            return QModelIndex()
        cnode = index.internalPointer()
        pnode = cnode.getItemParent()
        if not pnode or pnode == self.root:
            return QModelIndex()
        return self.createIndex(pnode.getItemPos(), 0, pnode)

    def index(self, row, column, parent=QModelIndex()):
        if not self.hasIndex(row, column, parent):
            return QModelIndex()
        if not parent.isValid():
            pnode = self.root
        else:
            pnode = parent.internalPointer()
        cnode = pnode.getItemChild(row)
        if not cnode:
            return QModelIndex()
        return self.createIndex(row, column, cnode)

    def data(self, index, role=Qt.DisplayRole):
        if role == Qt.DisplayRole:
            return index.internalPointer().getItemData(1)
        elif role == Qt.UserRole+1:
            return index.internalPointer().getItemData(0)
        return None

    def setData(self, index, value, role=Qt.EditRole):
        if role == Qt.EditRole:
            index.internalPointer().setItemData(index.column(), value)
            self.dataChanged.emit(index, index, [role])
            return True
        return False



    def contains(self, data):
        return False

    def tree_model_data_reset(self):
        nbranch = self.root.getRowCount()
        self.beginResetModel()
        for nth in range(nbranch):
            nodeparent = self.root.getItemChild(nth)
            nodeparent.clearChildren()
        self.root.clearChildren()
        self.endResetModel()

    def tree_model_data_update(self, data:list):
        if not data:
            return

        # Purified data already in 'tree'
        purified = []
        for d in data:
            if not self.contains(d):
                purified.append(d)

        # Categorize data by filename
        files = []
        group = []
        anchor = []
        for i in range(len(purified)):
            filename = os.path.basename(purified[i][4])
            if filename not in files:
                files.append(filename)
                # this file's elements list pos
                lpos = len(group)
                group.append([])
                group[lpos].append(i)
                # get position in root, if found, add to anchor, if not found, add it to root.
                under_root = False
                for j in range(self.root.getRowCount()):
                    # Here, root's children is different with real child probe node. root's children is only for display and convenience.
                    if filename == self.root.getItemChild(j).getItemData(1):
                        anchor.append(j)
                        under_root = True
                if not under_root:
                    # create new root child
                    anchor.append(self.root.getRowCount())
                    newnode = CustomCounterTreeItem([0, filename])
                    self.root.appendChild(newnode)

            else:
                lpos = files.index(filename)
                group[lpos].append(i)

        # group and anchor really matters
        for i in anchor:
            nodeparent = self.root.getItemChild(i)
            iparent = self.createIndex(i, 0, self.root)
            ncnts = nodeparent.getRowCount()
            nrows = len(group[i])
            self.beginInsertRows(iparent, ncnts, ncnts+nrows-1)
            for pos in group[i]:
                nodetarget = CustomCounterTreeItem(purified[pos])
                nodeparent.appendChild(nodetarget)
            self.endInsertRows()
                    
    # Whether this is needed or not
    def tree_model_data_append(self, data:list):
        nodeparent = self.root.getItemChild(0)
        iparent = self.createIndex(0, 0, self.root)
        startpos = nodeparent.getRowCount()
        stoppos = startpos+len(data)-1
        self.beginInsertRows(iparent, startpos, stoppos)
        for d in data:
            nodetarget = CustomCounterTreeItem(d)
            nodeparent.itemappend(nodetarget)
        self.endInsertRows()


class CustomCounterTreeView(QTreeView):
    def __init__(self, parent=None):
        super().__init__(parent)
        self.treedata = CustomCounterTreeModel()
        self.setModel(self.treedata)
        self.header().setVisible(False)
        self.expandAll()

    def tree_view_reset(self):
        self.treedata.tree_model_data_reset()

    def tree_view_renew(self, data:list):
        self.treedata.tree_model_data_reset()
        self.treedata.tree_model_data_update(data)
        self.expandAll()

    def tree_view_update(self, data:list):
        self.treedata.tree_model_data_update(data)
        self.expandAll()



#probe1 = [1, '2411001', True, 0, "/home/file1", 1.001, 1.002, 1.003, 1.004]
#probe2 = [1, '2411002', True, 0, "/home/file1", 1.001, 1.002, 1.003, 1.004]
#probe3 = [1, '2411003', True, 0, "/home/file1", 1.001, 1.002, 1.003, 1.004]
#probe4 = [1, '2411004', True, 0, "/home/file1", 1.001, 1.002, 1.003, 1.004]
#probe5 = [1, '2411005', True, 0, "/home/file1", 1.001, 1.002, 1.003, 1.004]
#probe6 = [2, '2411006', True, 0, "/home/file2", 2.001, 2.002, 2.003, 2.004]
#probe7 = [2, '2411007', True, 0, "/home/file2", 2.001, 2.002, 2.003, 2.004]
#probe8 = [3, '2411008', True, 0, "/home/file2", 3.001, 3.002, 3.003, 3.004]
#probe9 = [3, '2411009', True, 0, "/home/file2", 3.001, 3.002, 3.003, 3.004]
#probe10 = [4, '2411010', True, 0, "/home/file3", 4.001, 4.002, 4.003, 4.004]
#probe11 = [4, '2411011', True, 0, "/home/file3", 4.001, 4.002, 4.003, 4.004]
#probe12 = [5, '2411012', True, 0, "/home/file3", 5.001, 5.002, 5.003, 5.004]
#
#app = QApplication()
#win = CustomCounterTreeView()
#win.treeupdate([probe1, probe2, probe3, probe4])
#win.treerenew([probe1, probe2, probe3, probe4, probe5, probe6, probe7, probe8, probe9, probe10, probe11, probe12])
#win.resize(250, 600)
#win.show()
#app.exec()
